import log from "@/common/app/log.js";
import config from "@/common/app/config.js";
import store from "@/common/app/store.js";
import lang from "@/common/app/lang.js";
import assemble from "@/common/app/assemble.js";

export default {
  /**
   * getServerConfig 根据当前运行环境获取系统参数配置（主要是接口服务器地址及文件服务器地址）
   */
  getServerConfig() {
    let serverConfig = window.systemConfig.SERVER_CONFIG;
    let result = {};
    if (serverConfig) {
      if (process.env.NODE_ENV === "production") {
        log.debug("当前是发布环境，应用程序是通过“npm run build”创建的");
        result = JSON.parse(JSON.stringify(serverConfig.PRO || {}));
      } else {
        log.debug("当前是开发环境，应用程序是通过“npm run dev”创建的");
        result = JSON.parse(JSON.stringify(serverConfig.DEV || {}));
      }
    }
    return result;
  },

  /**
   * 根据系统配置获取接口请求的完整URL
   * 如果接口地址中没有包含http或者https的字符，则将配置的接口前缀拼接上
   * 如果带有http或者https则表示当前接口地址为完整的接口地址，不需要再拼接接口地址前缀
   * @param {String} url 原接口地址
   * @param {Boolean} isMock 是否使用本地模拟桩接口，可以针对某个接口进行模拟桩调用
   */
  getApiUrl(url, isMock) {
    if (url.indexOf("http://") !== 0 && url.indexOf("https://") !== 0) {
      const serverConfig = this.getServerConfig();
      // 如果未配置后台服务器URL，则使用当前服务器URL
      const currentUrl = window.location.protocol + "//" + window.location.host;
      // 如果当前接口是需要使用模拟桩接口，或者当前系统设置了模拟桩请求，则使用模拟桩服务器地址作为接口服务器地址
      let serverUrl =
        (serverConfig.localMock || isMock
          ? serverConfig.mockServer
          : serverConfig.serverUrl) || currentUrl;
      // 如果接口服务器地址的最后一个字符不是'/'，同时传入的url第一个字符不是'/'，则需要将服务器地址+'/'+接口地址
      if (serverUrl.lastIndexOf("/") !== serverUrl.length - 1) {
        serverUrl += "/";
      }
      if (!serverUrl || !serverUrl.length) {
        serverUrl = "/";
      }
      if (url.indexOf("/") === 0) {
        url = url.substring(1);
      }
      url = serverUrl + url;
    }
    return url;
  },
  /**
   * 根据系统配置获取WebSocket请求的完整URL
   * 如果接口地址中没有包含http或者https的字符，则将配置的接口前缀拼接上
   * 如果带有http或者https则表示当前接口地址为完整的接口地址，不需要再拼接接口地址前缀
   * @param {String} url 原接口地址
   * @param {Boolean} isMock 是否使用本地模拟桩接口，可以针对某个接口进行模拟桩调用
   */
  getSocketUrl(url, isMock) {
    // 如果未配置后台服务器URL，则使用当前服务器URL
    const currentProtocol = window.location.protocol;
    const currentHost = window.location.host;
    const currentUrl =
      (currentProtocol === "http:" ? "ws:" : "wss:") + "//" + currentHost;
    if (url.indexOf("ws://") !== 0 && url.indexOf("wss://") !== 0) {
      const serverConfig = this.getServerConfig();
      // 如果当前接口是需要使用模拟桩接口，或者当前系统设置了模拟桩请求，则使用模拟桩服务器地址作为接口服务器地址
      let socketUrl =
        (serverConfig.localMock || isMock
          ? serverConfig.mockServer
          : serverConfig.socketUrl) || currentUrl;
      // 如果接口服务器地址的最后一个字符不是'/'，同时传入的url第一个字符不是'/'，则需要将服务器地址+'/'+接口地址
      if (socketUrl.lastIndexOf("/") !== socketUrl.length - 1) {
        socketUrl += "/";
      }
      if (!socketUrl || !socketUrl.length) {
        socketUrl = "/";
      }
      if (url.indexOf("/") === 0) {
        url = url.substring(1);
      }
      url = socketUrl + url;
    }
    return url;
  },
  /**
   * 时间格式化
   * @param {Date || String || Number} time 待格式化的时间对象或者合法的时间字符串或者时间毫秒数
   * @param {String} formatter 时间格式化规范
   * @return {String} 格式化后的时间字符串
   */
  dateFormat(time = new Date(), formatter = "YYYY-mm-dd HH:MM:SS") {
    let date = time;
    if (typeof date === "string") {
      date = new Date(date.split("-").join("/"));
    }
    let ret;
    const opt = {
      "Y+": date.getFullYear().toString(), // 年
      "m+": (date.getMonth() + 1).toString(), // 月
      "d+": date.getDate().toString(), // 日
      "H+": date.getHours().toString(), // 时
      "M+": date.getMinutes().toString(), // 分
      "S+": date.getSeconds().toString(), // 秒
      "s+": date.getMilliseconds().toString(), // 毫秒
      // 有其他格式化字符需求可以继续添加，必须转化成字符串
    };
    for (let k in opt) {
      ret = new RegExp("(" + k + ")").exec(formatter);
      if (ret) {
        formatter = formatter.replace(
          ret[1],
          ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0")
        );
      }
    }
    return formatter;
  },

  /**
   * 字符串去前后空格操作，如果传入的字符串是null或undefined则返回空字符串，避免业务代码中对字符串进行空判断
   * @param {Object} str 待去空格的字符串
   */
  trim(str) {
    if (str === null || str === undefined) {
      return "";
    }
    str = str + "";
    return str.replace(/(^\s*)|(\s*$)/g, "");
  },

  /**
   * unRepeatArray 对象数组去重操作
   * @param {Array} resource 待去重的对象数组
   * @param {String} key 去重依据字段
   * @returns {Array} 去重后的数组
   */
  unRepeatArray(resource, key) {
    if (!resource || !resource.length || !key || !key.length) {
      return resource;
    }
    let tempData = [];
    let tempObj = {};
    resource.forEach((item) => {
      if (!tempObj[item[key]]) {
        tempData.push(item);
        tempObj[item[key]] = true;
      }
    });
    return tempData;
  },

  /**
   * 获取当前设备的UUID，自动计算的UUID
   */
  getUUID() {
    let uuid = new Date().getTime();
    let s = [];
    let hexDigits = "0123456789ABCDEF";
    for (let i = 0; i < 36; i++) {
      s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = "-";
    uuid = s.join("");
    return uuid;
  },

  /**
   * 将文本复制到剪切板中
   * @param {String || Number} text 待复制的文本内容
   */
  copyText(text = "") {
    if (text === null || text === undefined || text === "") {
      log.warn("待复制的文本内容为空");
      return;
    }
    text += "";
    let tag = document.createElement("input");
    tag.setAttribute("id", "copy_text_dom");
    tag.value = text;
    document.getElementsByTagName("body")[0].appendChild(tag);
    document.getElementById("copy_text_dom").select();
    document.execCommand("copy");
    document.getElementById("copy_text_dom").remove();
    log.debug("复制内容成功：", text);
  },

  /**
   * 计算传入的时间与当前时间的时间差
   * @param {Date || String || Number} dateTime 待计算的时间对象或时间字符串或时间毫秒数
   * @return {String} timeInterval 计算的结果，如：'刚刚'、'xx分钟前'、'xx小时前'、'xx天前'、'xx月前'、'xx年前'
   */
  getTimeInterval(dateTime = new Date()) {
    const now = new Date().getTime();
    // 如果传入的时间是一个字符串，则将字符串的日期分隔符由'-'修改为'/'，已适配IE及iOS的日期转换
    if (typeof dateTime === "string") {
      dateTime.split("-").join("/");
    }
    const time = new Date(dateTime).getTime();
    // 时间间隔值（秒数）
    const interval = (now - time) / 1000;
    // 小于60秒（一分钟内）展示刚刚
    let timeInterval = "刚刚";
    if (interval < 0) {
      timeInterval = "未来某个时间";
    } else if (interval >= 60 && interval < 3600) {
      // 大于一分钟，小于一小时，展示'xx分钟前'
      timeInterval = Math.floor(interval / 60) + "分钟前";
    } else if (interval >= 3600 && interval < 86400) {
      // 大于一个小时，小于一天，展示'xx小时前'
      timeInterval = Math.floor(interval / 3600) + "小时前";
    } else if (interval >= 86400 && interval < 2678400) {
      // 大于一天，小于一个月（31天），展示'xx天前'
      timeInterval = Math.floor(interval / 86400) + "天前";
    } else if (interval >= 2678400 && interval < 31622400) {
      // 大于一个月，小于一年（366天），展示'xx月前'
      timeInterval = Math.floor(interval / 2678400) + "月前";
    } else if (interval >= 31622400) {
      // 大于一年（366天），展示'xx年前'
      timeInterval = Math.floor(interval / 31622400) + "年前";
    }
    return timeInterval;
  },

  /**
   * 根据App当前设置的主题样式，获取主题对应的图片路径
   * @param {String} iconPath 主题目录下的图片路径
   * @param {Boolean} language 当前图片是否需要拼接语种路径
   * @param {Boolean} common 当前图片是否使用公共图片（非主题路径图片）
   *                  如common为true，则表示为公共图片，将图片路径前面拼接config中的COMMON_ICON_PATH配置的路径
   *                  如common为false，则表示为主题图片，则将图片路径前面拼接config中的THEME_ICON_PATH配置的路径
   * @return {String} result 根据当前主题拼接的图片访问路径
   */
  getIconByTheme(iconPath = "", language = false, common = false) {
    let prefixPath = [];
    // 判断使用主题目录还是公共图标库目录
    if (common) {
      prefixPath = prefixPath.concat(
        (config.COMMON_ICON_PATH || "").split("/")
      );
    } else {
      let themeIconPath = config.THEME_ICON_PATH || "";
      if (themeIconPath && themeIconPath.length) {
        prefixPath = prefixPath.concat(themeIconPath.split("/"));
        const currentTheme = store.getters.currentTheme;
        prefixPath.push(currentTheme);
      }
    }
    // 当前是否是多语种图片
    if (language) {
      let languagePath = config.LANGUAGE_ICON_PATH || "";
      if (languagePath && languagePath.length) {
        prefixPath = prefixPath.concat(languagePath.split("/"));
        const currentLanguage = store.getters.currentLanguage;
        prefixPath.push(currentLanguage);
      }
    }
    prefixPath = prefixPath.concat((iconPath || "").split("/"));
    prefixPath = prefixPath.filter((item) => {
      return item !== "";
    });
    return "/" + prefixPath.join("/");
  },

  /**
   * 根据App当前设置的语种，获取语种对应的文本
   * @param {String} str 文本路径
   * @return {String} result 获取对应语种的文本，如未获取到正确的文本，则返回文本路径字符串
   * @return {Object} param 获取到字符串后，将字符中的参数进行替换
   */
  lang(str = "", param = null) {
    let keys = str.split(".");
    let currentLanguage = store.getters.currentLanguage;
    let messageInfo = lang[currentLanguage] || {};
    let tempObj = null;
    for (let i = 0; i < keys.length; i++) {
      if (i === 0) {
        tempObj = messageInfo[keys[i]];
      } else if (
        tempObj &&
        tempObj[keys[i]] !== null &&
        tempObj[keys[i]] !== undefined
      ) {
        tempObj = tempObj[keys[i]];
      } else {
        tempObj = null;
        break;
      }
    }
    let result = str;
    if (tempObj !== null && typeof tempObj === "string") {
      result = tempObj;
    }
    if (param) {
      for (let key in param) {
        result = result.split("{" + key + "}").join(param[key]);
      }
    }
    return result;
  },

  /**
   * esc监听全屏
   */
  listenFullScreen: (flag, callback) => {
    if (flag === "add") {
      document.addEventListener("fullscreenchange", callback);
      document.addEventListener("mozfullscreenchange", callback);
      document.addEventListener("webkitfullscreenchange", callback);
      document.addEventListener("msfullscreenchange", callback);
      document.onmsfullscreenchange = callback;
    } else {
      document.removeEventListener("fullscreenchange", callback);
      document.removeEventListener("mozfullscreenchange", callback);
      document.removeEventListener("webkitfullscreenchange", callback);
      document.removeEventListener("msfullscreenchange", callback);
      document.onmsfullscreenchange = null;
    }
  },

  /**
   * 浏览器判断是否全屏
   */
  isFullScreen: () => {
    return (
      // 默认判断浏览器是否全屏
      document.isFullScreen ||
      // 未知，原应该是判断Firefox浏览器，但是该属性未生效
      document.mozIsFullScreen ||
      // 判断Chrome浏览器是否全屏
      document.webkitIsFullScreen ||
      // 判断IE浏览器是否全屏
      document.msFullscreenElement ||
      // 判断Firefox浏览器是否全屏
      document.fullscreenElement
    );
  },

  /**
   * 浏览器全屏
   */
  reqFullScreen: () => {
    if (document.documentElement.requestFullScreen) {
      // 默认设置浏览器全屏
      document.documentElement.requestFullScreen();
    } else if (document.documentElement.webkitRequestFullScreen) {
      // 设置Chrome浏览器全屏
      document.documentElement.webkitRequestFullScreen();
    } else if (document.documentElement.mozRequestFullScreen) {
      // 设置Firefox浏览器全屏
      document.documentElement.mozRequestFullScreen();
    } else if (document.documentElement.msRequestFullscreen) {
      // 设置IE浏览器全屏
      document.documentElement.msRequestFullscreen();
    }
  },

  /**
   * 浏览器退出全屏
   */
  exitFullScreen: () => {
    if (document.documentElement.requestFullScreen) {
      // 默认退出浏览器全屏
      document.exitFullScreen();
    } else if (document.documentElement.webkitRequestFullScreen) {
      // 退出Chrome浏览器全屏
      document.webkitCancelFullScreen();
    } else if (document.documentElement.mozRequestFullScreen) {
      // 退出Firefox浏览器全屏
      document.mozCancelFullScreen();
    } else if (document.documentElement.msRequestFullscreen) {
      // 退出IE浏览器全屏
      document.msExitFullscreen();
    }
  },
  /**
   * 判断当前浏览器是否是微信浏览器
   */
  isWeiXinBrowser() {
    let result = false;
    let ua = window.navigator.userAgent.toLowerCase();
    if (ua.match(/MicroMessenger/i) == "micromessenger") {
      log.debug("当前浏览器是微信浏览器");
      result = true;
    } else {
      log.debug("当前浏览器不是微信浏览器");
      result = false;
    }
    return result;
  },
  /**
   * 判断当前浏览器是否是IOS环境中的浏览器
   */
  isIOS() {
    let result = false;
    let ua = window.navigator.userAgent.toLowerCase();
    result = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    return result;
  },
  /**
   * 判断当前浏览器是否是IOS系统中的Safari浏览器
   */
  isIOSSafari() {
    let result = false;
    let ua = window.navigator.userAgent.toLowerCase();
    result = !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X.+Safari/);
    return result;
  },
  /**
   * 获取指定长度的随机字符串
   */
  randomString(length = 16) {
    const defaultstr =
      "abcdefghigklmnopqrstuvwxyzABCDEFGHJKMNPQRSTWXYZ0123456789";
    const strLength = defaultstr.length;
    let result = "";
    for (var i = 0; i < length; i++) {
      result += "" + defaultstr.charAt(Math.floor(Math.random() * strLength));
    }
    return result;
  },
  /**
   * 将 JSON 对象转换为 URL 查询字符串
   * @param {Object} params - 要转换的参数对象
   * @returns {string} 返回 URL 查询字符串 (不带问号)
   */
  jsonToQueryString(params = {}) {
    params = params || {};
    const searchParams = new URLSearchParams();

    const appendParams = (keyPrefix, value) => {
      if (value === null || value === undefined) return;

      if (Array.isArray(value)) {
        value.forEach((item) => searchParams.append(keyPrefix, item));
      } else if (typeof value === "object") {
        for (const [k, v] of Object.entries(value)) {
          appendParams(`${keyPrefix}.${k}`, v);
        }
      } else {
        searchParams.append(keyPrefix, value);
      }
    };

    for (const [key, value] of Object.entries(params)) {
      appendParams(key, value);
    }

    return searchParams.toString();
  },
  ...assemble.getAssembleData("utils"),
};
